#lang racket

(require "syntax.scm")

(provide parse-file)

(define (syntax-metadata stx)
  (list (cons 'source (syntax-source stx))
        (cons 'line (syntax-line stx))
        (cons 'column (syntax-column stx))))

(define (process-syntax-object stx)
  (let ((e (if (syntax? stx) (syntax-e stx) stx)))
    (cond ((or (number? e) (boolean? e) (string? e))
	   (syx 'atomic e (syntax-metadata stx)))
          ((symbol? e)
	   (syx 'id e (syntax-metadata stx)))
          ((pair? e)
	   (cons (process-syntax-object (car e))
		 (process-syntax-object (cdr e))))
          ((null? e) '())
          (else (error "unknown syntax object" stx)))))

(define (parse-file filename)
  (call-with-input-file filename
    (lambda (in)
      (port-count-lines! in)
      (let loop ()
        (let ((object (read-syntax filename in)))
          (if (eof-object? object)
              '()
              (cons (process-syntax-object object) (loop))))))))

#|
(list
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 1) (column . 1)))
  (syx 'id 't1 '((source . "t9.scm") (line . 1) (column . 8)))
  (list
   (list
    (syx 'id 'lambda '((source . "t9.scm") (line . 1) (column . 13)))
    (list (syx 'id 'x '((source . "t9.scm") (line . 1) (column . 21))))
    (list
     (syx 'id '+ '((source . "t9.scm") (line . 1) (column . 25)))
     (syx 'id 'x '((source . "t9.scm") (line . 1) (column . 27)))
     (syx 'id 'x '((source . "t9.scm") (line . 1) (column . 29)))))
   (syx 'atomic 4 '((source . "t9.scm") (line . 1) (column . 33)))))
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 3) (column . 1)))
  (syx 'id 'reverse-subtract '((source . "t9.scm") (line . 3) (column . 8)))
  (list
   (syx 'id 'lambda '((source . "t9.scm") (line . 4) (column . 3)))
   (list
    (syx 'id 'x '((source . "t9.scm") (line . 4) (column . 11)))
    (syx 'id 'y '((source . "t9.scm") (line . 4) (column . 13))))
   (list
    (syx 'id '- '((source . "t9.scm") (line . 4) (column . 17)))
    (syx 'id 'y '((source . "t9.scm") (line . 4) (column . 19)))
    (syx 'id 'x '((source . "t9.scm") (line . 4) (column . 21))))))
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 5) (column . 1)))
  (syx 'id 't2 '((source . "t9.scm") (line . 5) (column . 8)))
  (list
   (syx 'id 'reverse-subtract '((source . "t9.scm") (line . 5) (column . 12)))
   (syx 'atomic 7 '((source . "t9.scm") (line . 5) (column . 29)))
   (syx 'atomic 10 '((source . "t9.scm") (line . 5) (column . 31)))))
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 7) (column . 1)))
  (syx 'id 'add4 '((source . "t9.scm") (line . 7) (column . 8)))
  (list
   (syx 'id 'let '((source . "t9.scm") (line . 8) (column . 3)))
   (list
    (list
     (syx 'id 'x '((source . "t9.scm") (line . 8) (column . 9)))
     (syx 'atomic 4 '((source . "t9.scm") (line . 8) (column . 11)))))
   (list
    (syx 'id 'lambda '((source . "t9.scm") (line . 9) (column . 5)))
    (list (syx 'id 'y '((source . "t9.scm") (line . 9) (column . 13))))
    (list
     (syx 'id '+ '((source . "t9.scm") (line . 9) (column . 17)))
     (syx 'id 'x '((source . "t9.scm") (line . 9) (column . 19)))
     (syx 'id 'y '((source . "t9.scm") (line . 9) (column . 21)))))))
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 11) (column . 1)))
  (syx 'id 't3 '((source . "t9.scm") (line . 11) (column . 8)))
  (list
   (syx 'id 'add4 '((source . "t9.scm") (line . 11) (column . 12)))
   (syx 'atomic 6 '((source . "t9.scm") (line . 11) (column . 17)))))
 (list
  (syx 'id 'define '((source . "t9.scm") (line . 13) (column . 1)))
  (syx 'id 'main '((source . "t9.scm") (line . 13) (column . 8)))
  (list
   (syx 'id 'begin '((source . "t9.scm") (line . 13) (column . 14)))
   (list
    (syx 'id 'print '((source . "t9.scm") (line . 13) (column . 21)))
    (syx 'id 't1 '((source . "t9.scm") (line . 13) (column . 27))))
   (list
    (syx 'id 'print '((source . "t9.scm") (line . 14) (column . 21)))
    (syx 'id 't2 '((source . "t9.scm") (line . 14) (column . 27))))
   (list
    (syx 'id 'print '((source . "t9.scm") (line . 15) (column . 21)))
    (syx 'id 't3 '((source . "t9.scm") (line . 15) (column . 27))))
   (list
    (syx 'id 'print '((source . "t9.scm") (line . 16) (column . 21)))
    (syx 'atomic "8 3 10?" '((source . "t9.scm") (line . 16) (column . 27)))))))

|#
